package contegor.scire.core;


/**
 * {@link Primitive} implementation.
 * Stores internally the last modification time.
 * 
 * @version $Revision$
 * @author  Héctor Cirbián Pousa ($Author$)
 */
@Version("$Id$")
public class PrimitiveImpl extends ConceptImpl implements Primitive {
  private static final long serialVersionUID = 526938642478762632L;
  
  private Object value;
  private long modificationTime;

  private Object preValue;
  private long preModificationTime;

  private boolean modified;

  protected PrimitiveImpl(long creationTime, TransactionId transactionId, IdFragment idFragment) {
    super(creationTime, transactionId, idFragment);
    this.value = null;
    this.modificationTime = 0;
    this.preValue = null;
    this.preModificationTime = 0;
    this.modified = false;
  }
 
  protected PrimitiveImpl(long creationTime, TransactionId transactionId, IdFragment idFragment, Object value) {
    super(creationTime, transactionId, idFragment);
    this.value = value;
    this.modificationTime = System.currentTimeMillis();
    this.preValue = null;
    this.preModificationTime = 0;
    this.modified = false;
  }

  @Override
  public Object getValue() {
    return this.value;
  }

  @Override
  public Class<?> getType() {
    Object aux = this.value;
    if (aux != null)
      return aux.getClass();
    return null;
  }

  protected synchronized void setValue(long modificationTime, Object value) throws WrongStateException {
    Class<?> type = getType();
    if (type != null)
      if (!type.equals(value.getClass()))
        throw new WrongStateException("It's forbidden to change the type of a primitive.");
    this.modified = true;
    if (this.preValue == null) {
      this.preValue = this.value;
      this.preModificationTime = this.modificationTime;
    }
    this.value = value;
    this.modificationTime = modificationTime;
  }

  protected synchronized void rollback() {
    if (this.modified) {
      this.value = this.preValue;
      this.modificationTime = this.preModificationTime;
      this.modified = false;
    }
  }

  protected synchronized void commit() {
    this.preValue = null;
    this.preModificationTime = 0;
    this.modified = false;
  }

  public long getModificationTime() {
    return this.modificationTime;
  }
}
